home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib25 / _divmods.s < prev    next >
Text File  |  1992-12-12  |  3KB  |  96 lines

  1. | long division and modulus routines
  2. |
  3. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  4. |
  5. |
  6. | Revision 1.1, kub 03-90
  7. | first version, replaces the appropriate routine from fixnum.s.
  8. | Should be faster in more common cases. Division is done by 68000 divu
  9. | operations if divisor is only 16 bits wide. Otherwise the normal division
  10. | algorithm as described in various papers takes place. The division routine
  11. | delivers the quotient in d0 and the remainder in d1, thus the implementation
  12. | of the modulo operation is trivial. We gain some extra speed by inlining
  13. | the division code here instead of calling __udivsi3.
  14.  
  15.     .text
  16.     .even
  17.     .globl    __divsi3, ___divsi3, .ldiv
  18.     .globl    __modsi3, ___modsi3, .lrem
  19.  
  20. .ldiv:
  21. __divsi3:
  22. ___divsi3:
  23.     movel    d2,a0        | save registers
  24.     movel    d3,a1
  25.     clrw    sp@-        | sign flag
  26.     clrl    d0        | prepare result
  27.     movel    sp@(10),d2    | get divisor
  28.     beq    9f        | divisor = 0 causes a division trap
  29.     bpl    0f        | divisor < 0 ?
  30.     negl    d2        | negate it
  31.     notw    sp@        | remember sign
  32. 0:    movel    sp@(6),d1    | get dividend
  33.     bpl    0f        | dividend < 0 ?
  34.     negl    d1        | negate it
  35.     notw    sp@        | remember sign
  36. 0:
  37. |== case 1) divident < divisor
  38.     cmpl    d2,d1        | is divident smaller then divisor ?
  39.     bcs    8f        | yes, return immediately
  40. |== case 2) divisor has <= 16 significant bits
  41.     tstw    sp@(10)
  42.     bne    2f        | divisor has only 16 bits
  43.     movew    d1,d3        | save dividend
  44.     clrw    d1        | divide dvd.h by dvs
  45.     swap    d1
  46.     beq    0f        | (no division necessary if dividend zero)
  47.     divu    d2,d1
  48. 0:    movew    d1,d0        | save quotient.h
  49.     swap    d0
  50.     movew    d3,d1        | (d0.h = remainder of prev divu)
  51.     divu    d2,d1        | divide dvd.l by dvs
  52.     movew    d1,d0        | save quotient.l
  53.     clrw    d1        | get remainder
  54.     swap    d1
  55.     bra    8f        | and return
  56. |== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
  57. 2:
  58.     moveq    #31,d3        | loop count
  59. 3:
  60.     addl    d1,d1        | shift divident ...
  61.     addxl    d0,d0        |  ... into d0
  62.     cmpl    d2,d0        | compare with divisor
  63.     bcs    0f
  64.     subl    d2,d0        | big enough, subtract
  65.     addw    #1,d1        | and note bit into result
  66. 0:
  67.     dbra    d3,3b
  68.     exg    d0,d1        | put quotient and remainder in their registers
  69. 8:
  70.     tstw    sp@(6)        | must the remainder be corrected ?
  71.     bpl    0f
  72.     negl    d1        | yes, apply sign
  73. | the following line would be correct if modulus is defined as in algebra
  74. |    addl    sp@(6),d1    | algebraic correction: modulus can only be >= 0
  75. 0:    tstw    sp@+        | result should be negative ?
  76.     bpl    0f
  77.     negl    d0        | yes, negate it
  78. 0:
  79.     movel    a1,d3
  80.     movel    a0,d2
  81.     rts
  82. 9:
  83.     divu    d2,d1        | cause division trap
  84.     bra    8b        | back to user
  85.  
  86.  
  87. .lrem:
  88. __modsi3:
  89. ___modsi3:
  90.     movel    sp@(8),sp@-    | push divisor
  91.     movel    sp@(8),sp@-    | push dividend
  92.     jbsr    __divsi3
  93.     addql    #8,sp
  94.     movel    d1,d0        | return the remainder in d0
  95.     rts
  96.